package ${packagePrefix}.${domainObjectName?lower_case}.app.service.excel;

import ${packagePrefix}.${domainObjectName?lower_case}.app.converter.${domainObjectName}ExcelConverter;
import ${packagePrefix}.${domainObjectName?lower_case}.app.service.${domainObjectName}Service;
import ${packagePrefix}.${domainObjectName?lower_case}.client.api.excel.${domainObjectName}ExcelServiceI;
import ${packagePrefix}.${domainObjectName?lower_case}.client.dto.${domainObjectName}DTO;
import ${packagePrefix}.${domainObjectName?lower_case}.client.dto.excel.${domainObjectName}ExcelDTO;
import ${packagePrefix}.${domainObjectName?lower_case}.domain.${domainObjectName};
import ${packagePrefix}.${domainObjectName?lower_case}.domain.gateway.${domainObjectName}Gateway;
import com.alibaba.cola.exception.BizException;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

<#if generateComments>
/**
 * ${domainObjectName} Excel导入导出服务
 * <p>
 * 提供Excel数据的导入和导出功能
 * </p>
 *
 * @author Auto Generated
 */
</#if>
@Slf4j
@Service
public class ${domainObjectName}ExcelService implements ${domainObjectName}ExcelServiceI {

    @Autowired
    private ${domainObjectName}Gateway ${domainObjectName?uncap_first}Gateway;

    @Autowired
    private ${domainObjectName}Service ${domainObjectName?uncap_first}Service;
    
    @Autowired
    private ${domainObjectName}ExcelConverter ${domainObjectName?uncap_first}ExcelConverter;

    @Override
    public void exportTemplate(HttpServletResponse response) throws IOException {
        // 设置响应头
        setExcelResponseHeaders(response, ${domainObjectName}ExcelDTO.IMPORT_FILE_NAME);
        
        // 生成模板数据并导出
        List<${domainObjectName}ExcelDTO> templateData = ${domainObjectName}ExcelDTO.buildImportTemplateData();
        EasyExcel.write(response.getOutputStream(), ${domainObjectName}ExcelDTO.class)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("数据导入模板")
                .doWrite(templateData);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importData(MultipartFile file) {
        try {
            // 读取Excel文件并解析为对象列表
            List<${domainObjectName}ExcelDTO> excelDataList = EasyExcel.read(file.getInputStream())
                    .head(${domainObjectName}ExcelDTO.class)
                    .sheet()
                    .doReadSync();
            
            // 数据校验
            validateImportData(excelDataList);
            
            // 转换为领域对象并批量保存
            List<${domainObjectName}> entityList = ${domainObjectName?uncap_first}ExcelConverter.convertToEntityList(excelDataList);
            ${domainObjectName?uncap_first}Gateway.batchSave(entityList);
            
            log.info("成功导入{}条{}数据", entityList.size(), "${domainObjectName}");
        } catch (IOException e) {
            log.error("导入Excel文件失败", e);
            throw new BizException("文件读取失败：" + e.getMessage());
        }
    }

    @Override
    public void exportData(HttpServletResponse response) throws IOException {
        // 设置响应头
        setExcelResponseHeaders(response, ${domainObjectName}ExcelDTO.EXPORT_FILE_NAME);
        
        // 查询所有数据
        List<${domainObjectName}> entityList = ${domainObjectName?uncap_first}Gateway.findAll();
        
        // 转换为Excel数据并导出
        List<${domainObjectName}ExcelDTO> excelDataList = ${domainObjectName?uncap_first}ExcelConverter.convertToExcelDTOList(entityList);
        EasyExcel.write(response.getOutputStream(), ${domainObjectName}ExcelDTO.class)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("数据导出")
                .doWrite(excelDataList);
    }

    @Override
    public void exportDataByIds(HttpServletResponse response, List<Long> ids) throws IOException {
        // 设置响应头
        setExcelResponseHeaders(response, ${domainObjectName}ExcelDTO.EXPORT_FILE_NAME);
        
        // 查询指定ID的数据
        List<${domainObjectName}> entityList = new ArrayList<>();
        if (ids != null && !ids.isEmpty()) {
            entityList = ${domainObjectName?uncap_first}Gateway.findByIds(ids);
        }
        
        // 转换为Excel数据并导出
        List<${domainObjectName}ExcelDTO> excelDataList = ${domainObjectName?uncap_first}ExcelConverter.convertToExcelDTOList(entityList);
        EasyExcel.write(response.getOutputStream(), ${domainObjectName}ExcelDTO.class)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("数据导出")
                .doWrite(excelDataList);
    }

    /**
     * 校验导入数据
     *
     * @param excelDataList Excel数据列表
     */
    private void validateImportData(List<${domainObjectName}ExcelDTO> excelDataList) {
        if (excelDataList == null || excelDataList.isEmpty()) {
            throw new BizException("导入数据不能为空");
        }
        
        // 此处可添加更多业务相关的数据校验逻辑
        for (int i = 0; i < excelDataList.size(); i++) {
            ${domainObjectName}ExcelDTO item = excelDataList.get(i);
            // 示例：校验必填字段
            // if (StringUtils.isBlank(item.getName())) {
            //     throw new BizException("第" + (i + 2) + "行：名称不能为空");
            // }
        }
    }

    /**
     * 设置Excel响应头
     *
     * @param response  HTTP响应对象
     * @param fileName  文件名
     * @throws IOException IO异常
     */
    private void setExcelResponseHeaders(HttpServletResponse response, String fileName) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
    }

    <#if generateComments>/**
     * 导入Excel数据
     * 
     * @param file Excel文件
     * @param dataConsumer 数据处理函数
     * @return 导入记录数
     */
    </#if>
    public int importExcel(MultipartFile file, Consumer<List<${domainObjectName}ExcelDTO>> dataConsumer) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("Excel文件不能为空");
        }
        
        try {
            ${domainObjectName}ExcelReadListener<${domainObjectName}ExcelDTO> readListener = 
                new ${domainObjectName}ExcelReadListener<>(dataConsumer);
            
            EasyExcel.read(file.getInputStream(), ${domainObjectName}ExcelDTO.class, readListener)
                .sheet()
                .doRead();
            
            return readListener.getTotalCount();
        } catch (IOException e) {
            log.error("导入Excel异常", e);
            throw new RuntimeException("导入Excel失败: " + e.getMessage());
        }
    }
    
    <#if generateComments>/**
     * 导出Excel数据
     * 
     * @param response HTTP响应对象
     * @param dataList 要导出的数据列表
     * @param fileName 导出文件名(不含扩展名)
     */
    </#if>
    public void exportExcel(HttpServletResponse response, List<${domainObjectName}ExcelDTO> dataList, String fileName) {
        try {
            // 设置文件名
            String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String encodedFileName = URLEncoder.encode(fileName + "-" + dateTime, StandardCharsets.UTF_8);
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx");
            
            // 写入Excel
            EasyExcel.write(response.getOutputStream(), ${domainObjectName}ExcelDTO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽
                .sheet("数据")
                .doWrite(dataList);
        } catch (IOException e) {
            log.error("导出Excel异常", e);
            throw new RuntimeException("导出Excel失败: " + e.getMessage());
        }
    }
    
    <#if generateComments>/**
     * 获取Excel模板
     * 
     * @param response HTTP响应对象
     * @param fileName 模板文件名(不含扩展名)
     */
    </#if>
    public void getExcelTemplate(HttpServletResponse response, String fileName) {
        try {
            // 设置文件名
            String encodedFileName = URLEncoder.encode(fileName + "-模板", StandardCharsets.UTF_8);
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx");
            
            // 写入空模板
            EasyExcel.write(response.getOutputStream(), ${domainObjectName}ExcelDTO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽
                .sheet("模板")
                .doWrite(List.of());
        } catch (IOException e) {
            log.error("生成Excel模板异常", e);
            throw new RuntimeException("生成Excel模板失败: " + e.getMessage());
        }
    }
} 